package pl.medec.formmanager.controllers 
{
	import pl.medec.formmanager.FormManager;
	import pl.medec.formmanager.validators.IValidator;

	import flash.display.DisplayObject;
	import flash.events.FocusEvent;
	import flash.text.TextField;

	/**
	 * @author Piotr Mederak
	 */
	public class InputController 
	{
		public var textField:TextField;
		public var validator:Class;
		public var required:Boolean = false;
		public var clearDefaultText:Boolean = false;
		public var errorInfoDisplayObject:DisplayObject;
		public var errorBorderColor:Number;
		private var _defaultDescription:String;
		private var errorInfoString:String;
		private var userText:String;
		private var errorInfoFunction:Function;
		private var _isValid:Boolean;
		public var errorDetails:Object;

		/**
		 * @param inputFiled Pole tekstowe
		 * @param validator Sposob walidacji pola
		 * @param required Czy pole musi byc uzupelnione
		 * @param clearDefaultText Czy wyczyscic pole po kliknieciu w nie
		 * @param errorInfo Jesli DisplayObject - zostanie on wyswietlony w przypadku bledu. Jesli String - zostanie on wpisany do pola tekstowego, jesli Function - zostanie ona wywolana
		 */
		public function InputController(inputFiled:TextField,validator:Class, required:Boolean = false, clearDefaultText:Boolean = false, errorInfo:* = null, errorBorderColor:Number = NaN) 
		{
			this.textField = inputFiled;
			this.validator = validator;
			this.required = required;
			this.clearDefaultText = clearDefaultText;
			
			if(errorInfo) 
			{
				if(errorInfo is DisplayObject) 
				{
					this.errorInfoDisplayObject = errorInfo as DisplayObject;
				}
				else if(errorInfo is String) 
				{
					this.errorInfoString = errorInfo as String;
				}
				else if(errorInfo is Function) 
				{
					this.errorInfoFunction = errorInfo as Function;
				}
			}
			
			this.errorBorderColor = errorBorderColor;
			
			if(this.errorBorderColor) 
			{
				this.textField.borderColor = this.errorBorderColor;
			}
				
			if(this.errorInfoDisplayObject) 
			{
				this.errorInfoDisplayObject.visible = false;
			}
			
			if(this.clearDefaultText) 
			{
				this._defaultDescription = this.textField.text;
				
				this.textField.addEventListener( FocusEvent.FOCUS_IN, onFocusIn );
				this.textField.addEventListener( FocusEvent.FOCUS_OUT, onFocusOut );
			}
		}

		public function toString():String 
		{
			return "InputController " + this.textField.name;
		}

		/**
		 * zwraca zawartosc pola tekstowego bez domyslnej wartosci
		 */
		public function getInputText():String 
		{
			return FormManager.trim( (this.clearDefaultText && this.textField.text == this._defaultDescription) ? '' : this.textField.text );
		}

		/**
		 * waliduje pole tekstowe
		 * 
		 * @param isBrutalValid Jesli true, wtedy za walidacje odpowiadac bedzie nie walidator, a kolejny parametr - isValid
		 * @param isValid Jesli isBrutalValid jest true, wtedy ten parametr bedzie odpowiadal za walidacje, nie wlasciwy walidator
		 */
		public function validate(isBrutalValid:Boolean = false, isValid:Boolean = false):Boolean 
		{
			trace( 'isBrutalValid: ' + (isBrutalValid) );
			trace( 'isValid: ' + (isValid) );
			
			var result:Boolean;
			if(!isBrutalValid) 
			{
				var C:Class = (this.validator as Class);
				var v:IValidator = new C( );
			
				result = v.validate( this.getInputText( ) ); 
                
				this.errorDetails = v.details;
			
				v = null;
			} 
			else 
			{
				result = isValid;
			}
            
			if(!this.required && this.textField.text == this._defaultDescription) 
			{
				result = true;
			}
			
			if(!result && this.errorInfoDisplayObject) 
			{
				this.errorInfoDisplayObject.visible = true;
			}
			else if(result && this.errorInfoDisplayObject) 
			{
				this.errorInfoDisplayObject.visible = false;
			}
			
			if(!result && this.errorInfoFunction != null) 
			{
				this.errorInfoFunction( );
			}
			
			trace( 'this.errorInfoString: ' + (this.errorInfoString) );
			trace( 'result: ' + (result) );
			if(!result && this.errorInfoString) 
			{
				if(this.textField.text != this.errorInfoString) 
				{
					this.userText = this.textField.text;
				}
				this.textField.text = this.errorInfoString;
			}
			
			if(!result && this.errorBorderColor) 
			{
				this.textField.border = true;
			}
			else if(result && this.errorBorderColor) 
			{
				this.textField.border = false;
			}
			
			return result;
		}

		public function destroy():void 
		{
			this.textField.removeEventListener( FocusEvent.FOCUS_IN, onFocusIn );
			this.textField.removeEventListener( FocusEvent.FOCUS_OUT, onFocusOut );
		}

		private function onFocusIn(event:FocusEvent):void 
		{
			
			if(this.errorInfoString) 
			{
				if(this.textField.text == this.errorInfoString) 
				{
					this.textField.text = this.userText;
				}
			}
			
			if(this.clearDefaultText && this.textField.text == this._defaultDescription) 
			{
				this.textField.text = '';
				//this.textField.stage.focus = this.textField;
				trace( 'clear ' + this.textField.text ); 
			}
            
			if(this.errorInfoDisplayObject) 
			{
				this.errorInfoDisplayObject.visible = false;
			}
			else if(this.errorInfoDisplayObject) 
			{
				this.errorInfoDisplayObject.visible = false;
			}
		}

		private function onFocusOut(event:FocusEvent):void 
		{
			trace( 'focus out' );
			if(this.clearDefaultText && FormManager.trim( this.textField.text ) == '') 
			{
				this.textField.text = this._defaultDescription;
			}
			
			this._isValid = this.validate( );
			
			trace( 'this.textField.text: ' + (this.textField.text) );
		}

		public function backToDefaultDescription():void 
		{
			this.textField.text = this._defaultDescription;
		}

		public function get defaultDescription():String 
		{
			return _defaultDescription;
		}

		public function set defaultDescription(defaultDescription:String):void 
		{
			_defaultDescription = defaultDescription;
		}

		public function get isValid():Boolean 
		{
			return _isValid;
		}

		public function get value():String 
		{
			return (this.textField.text == this._defaultDescription) ? '' : this.textField.text;
		}
	}
}
